<?php
function __autoload($class_name) {
    $class_name = camelcasify($class_name);
    
    if(stripos($class_name, "Controller") === false) {
        require(MODELS_PATH . "$class_name.php");
    }
    else {
        require(CONTROLLERS_PATH . "$class_name.php");
    }
}

function php_fw_exception_handler($e) {
  echo $e->getMessage();
  return true;
}

function php_fw_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
  if(IS_PRODUCTION) {
    render_500_error();
    return true;
  }
  
  $error_output = '<html>' .
    '<head>' .
      '<meta http-equiv="Content-type" content="text/html; charset=utf-8">' .
      '<title>Error Found</title>' .
      '<style type="text/css">' .
        'html {background-color:#B80000;}' .
        'body {background-color:white;width:800px;margin:20px auto;padding:10px;border:1px solid black;}' .
        'h1 {text-align:center;color:#B80000;text-shadow:2px 2px 0px #bbb;}' .
        'h1 strong {color:black;font-style:italic;}' .
        'dt {margin:10px 0px 5px 0px;padding:10px;border:1px black solid;background-color:#B80000;font-weight:bold;font-size:12pt;color:white;text-shadow:1px 1px 0px black;}' .
        'dl {margin:0px 20px 30px 20px;}' .
        'dl span {margin-right:20px;font-size:8pt;color:#aaa;}' .
        'dl strong {color:#B80000;}' .
      '</style>' .
    '</head>' .
    '<body>';
    
  $corrupted_file = file_get_contents($errfile);
  $lines = explode("\n", $corrupted_file);
  $start_line = ($errline - 4);
  $end_line = ($errline + 2);
  for($i = $start_line; $i <= $end_line; $i++) {
    if($i < 0) {
      continue;
    }
    if(isset($lines[$i])) {
      $current_line = trim($lines[$i]);
      if($i == $errline - 1) {
        $current_line = "<strong>$current_line</strong>";
      }
      $extracted_lines .= "<span>$i</span> " . $current_line . "<br />";
    }
  }
    
  $error_info = '<h1>Error with level <strong>%s</strong> found</h1>' .
    '<dl>' .
      '<dt>Error Message</dt>' .
      "<dl>$errstr</dl>" .
      '<dt>File where error occured</dt>' .
      "<dl>$errfile</dl>" .
      '<dt>Line where error occured</dt>' .
      "<dl>$errline</dl>" .
      '<dt>Extracted lines around error</dt>' .
      "<dl>$extracted_lines</dl>" .
      '<dt>Error context</dt>' .
      "<dl>" . var_export($errcontext, true) . "</dl>" .
      '<dt>Backtrace</dt>' .
      '<dl>' . nl2br(var_export(debug_backtrace(), true)) . '</dl>' .
    '</dl>';
  
  switch ($errno) {
    /* Fatal run-time errors.
     * These indicate errors that can not be recovered from, such as a memory allocation problem. 
     * Execution of the script is halted.
     */
    case E_ERROR:
    $error_level = "E_ERROR";
    break;
    
    /* Run-time warnings (non-fatal errors).
     * Execution of the script is not halted.
     */
    case E_WARNING:
    $error_level = "E_WARNING";
    break;
    
    /* Compile-time parse errors.
     * Parse errors should only be generated by the parser.
     */
    case E_PARSE:
    $error_level = "E_PARSE";
    break;
    
    /* Run-time notices.
     * Indicate that the script encountered something that could indicate an error, but could also happen in the normal course of running a script. 
     */
    case E_NOTICE:
    $error_level = "E_NOTICE";
    return true;
    break;
    
    /* Fatal errors that occur during PHP's initial startup.
     * This is like an E_ERROR, except it is generated by the core of PHP. 
     */
    case E_CORE_ERROR:
    $error_level = "E_CORE_ERROR";
    break;
    
    /* Warnings (non-fatal errors) that occur during PHP's initial startup.
     * This is like an E_WARNING, except it is generated by the core of PHP. 
     */
    case E_CORE_WARNING:
    $error_level = "E_CORE_WARNING";
    break;
    
    /* Fatal compile-time errors.
     * This is like an E_ERROR, except it is generated by the Zend Scripting Engine. 
     */
    case E_COMPILE_ERROR:
    $error_level = "E_COMPILE_ERROR";
    break;
    
    /* Compile-time warnings (non-fatal errors).
     * This is like an E_WARNING, except it is generated by the Zend Scripting Engine.
     */
    case E_COMPILE_WARNING:
    $error_level = "E_COMPILE_WARNING";
    break;
    
    /* User-generated error message.
     * This is like an E_ERROR, except it is generated in PHP code by
     * using the PHP function trigger_error(). 
     */
    case E_USER_ERROR:
    $error_level = "E_USER_ERROR";
    break;
    
    /* User-generated warning message.
     * This is like an E_WARNING, except it is generated in PHP code by
     * using the PHP function trigger_error(). 
     */
    case E_USER_WARNING:
    $error_level = "E_USER_WARNING";
    break;
    
    /* User-generated notice message.
     * This is like an E_NOTICE, except it is generated in PHP code by
     * using the PHP function trigger_error(). 
     */
    case E_USER_NOTICE:
    $error_level = "E_USER_NOTICE";
    break;
    
    /* Enable to have PHP suggest changes to your code which will ensure the
     * best interoperability and forward compatibility of your code.
     */
    case E_STRICT:
    $error_level = "E_STRICT";
    break;
    
    /* Catchable fatal error. It indicates that a probably dangerous 
     * error occured, but did not leave the Engine in an unstable state. 
     * If the error is not caught by a user defined handle (see also 
     * set_error_handler()), the application aborts as it was an E_ERROR.
     */
    case E_RECOVERABLE_ERROR:
    $error_level = "E_RECOVERABLE_ERROR";
    break;
    
    /* Run-time notices. Enable this to receive warnings about code that
     * will not work in future versions. 
     */
    case E_DEPRECATED:
    $error_level = "E_DEPRECATED";
    break;
    
    /* User-generated warning message. This is like an E_DEPRECATED, except it
     * is generated in PHP code by using the PHP function trigger_error(). 
     */
    case E_USER_DEPRECATED:
    $error_level = "E_USER_DEPRECATED";
    break;
  }
  
  $error_info = sprintf($error_info, $error_level);
  
  $error_output .= $error_info .
    '</body>' .
    '</html>';
    
  global $output;
  $output["html"] = $error_output;
  render_content();
  
  return true;
}

function render_content($content = "html") {
    global $output;
    echo $output[$content];
}

function output() {
    global $maped_routes;
    
    if(empty($maped_routes) or empty($maped_routes[camelcasify(get_current_model())])) {
        $model = camelcasify(get_current_model());
        $action = get_current_action();
        $class = $model . "Controller";
    }
    else {
        $current_route = $maped_routes[camelcasify(get_current_model())];
        $model = camelcasify($current_route["model"]);
        $action = $current_model["action"];
        $class = $model . 'Controller';
    }
    
    $vars = get_class_vars($class);
    
    if($vars === false) {
      throw new Exception("Controller: <strong>$class</strong> doesn't exist.");
      return false;
    }
    
    if(!is_script()) {
        if(property_exists($class, $action . "_layout")) {
            $layout = $vars[$action . "_layout"];
        }
        else {
            $layout = $vars["default_layout"];
        }
        
        if(property_exists($class, "custom_layout_path")) {
          $layout_path = $vars['custom_layout_path'];
        }
        else {
          $layout_path = LAYOUTS_PATH;
        }
        
        require($layout_path . "$layout.php");
    }
}

function include_plugin($name) {
    require(PLUGINS_PATH . $name . ".php");
}

function include_core_library($name) {
    require(CORE_PATH . $name . ".php");
}

function is_post() {
    if(isset($_POST) and !empty($_POST)) {
        $args = func_get_args();
        if(empty($args)) {
            return true;
        }
        else {
            $ok = true;
            foreach($args as $arg) {
                if(isset($_POST[$arg]) and !empty($_POST[$arg])) {
                    continue;
                }
                else {
                    return false;
                }
            }
        }
    }
    else {
        return false;
    }
}

function redirect_to_root() {
    header("Location: " . ROOT);
    exit();
}

function is_script() {
    return ($_GET["script"] == true) ? true : false;
}

function get_current_model() {
    if(!empty($_GET["model"]) and isset($_GET["model"])) {
        return camelcasify($_GET["model"]);
    }
    else {
        return camelcasify(DEFAULT_CONTROLLER);
    }
}

function get_current_action() {
    if(!empty($_GET["action"]) and isset($_GET["action"])) {
        return $_GET["action"];
    }
    else {
        return "index";
    }
}

function get_current_id() {
    if(!empty($_GET["id"]) and isset($_GET["id"])) {
        return $_GET["id"];
    }
    else {
        return null;
    }
}

function redirect_to($options = array()) {
    if(empty($options["model"]) or empty($options["action"])) {
        $location = $options;
    }
    else {
        $location = ROOT . underscorify($options["model"]) . '/' . ((empty($options["id"])) ? '' : $options["id"] . '/') .  $options["action"];
    }
    header("Location: $location");
    exit();
}

function render_404_error() {
    header("Location: " . PUBLIC_PATH . "404.php");
}

function render_500_error() {
  $called_uri = base64_encode($_SERVER['REQUEST_URI']);
  header("Location: " . PUBLIC_PATH . "500.php?called_uri=$called_uri");
}

function setup_get_parameters() {
    $url = $_SERVER['REQUEST_URI'];
    $url = parse_url($url);
    if(empty($url["query"])) {
        return true;
    }
    parse_str($url["query"], $parameters);
    foreach($parameters as $key => $value) {
        $_GET[$key] = $value;
    }
    return true;
}

function absolute_path($url) {
    $server_root = 'http://' . $_SERVER['SERVER_ADDR'];
    $page_root = $server_root . '/' . substr(ROOT, 1);
    $absolute_path = $page_root . $url;
    return $absolute_path;
}

function image_link($image) {
  return IMAGES_PATH . $image;
}

$exec_time = null;

function start_execution_time() {
  global $exec_time;
  $exec_time = microtime(true);
}

function end_execution_time() {
  global $exec_time;
  $exec_time = microtime(true) - $exec_time;
}

function get_execution_time($end = false) {
  global $exec_time;
  if($end) {
    end_execution_time();
  }
  return round($exec_time, 2);
}

function get_query_count($without_fields = false) {
  global $db;
  return $db->get_query_count($without_fields);
}

function auto_stripslashes($value) {
  if(AUTO_STRIPSLASHES and !is_numeric($value) and get_class($value) === false) {
    $value = stripslashes($value);
  }
  return $value;
}

function underscorify($str) {
  $arr = preg_split('/([A-Z][^A-Z]*)/', $str, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
  $ret = implode("_", $arr);
  $ret = strtolower($ret);
  return $ret;
}

function camelcasify($str) {
  $arr = explode("_", $str);
  $arr = array_map("ucfirst", $arr);
  $ret = implode("", $arr);
  return $ret;
}
?>